<?php
namespace Matrix;

/**
 * 字符串类
 *
 * 封装了一些常用的字符串方法
 *
 * 产生一个随机字符串:
 * <code>
 * Str::random(40);
 * </code>
 *
 * 限制英语单词的个数:
 * <code>
 * Str::words('I love you', 2);	// I love ...
 * </code>
 *
 * 将字符串转换为一个标题:
 * <code>
 * Str::title('i love you');	// I Love You
 * </code>
 */
class Str
{
	/**
	 * 复数类的实例
	 *
	 * @var mixed
	 */
	public static $pluralizer;
	
	/**
	 * 得到默认字符串编码
	 *
	 * @return	string
	 */
	public static function encoding()
	{
		return Config::get('application.encoding'); 
	}
	
	/**
	 * 得到字符串长度
	 *
	 * @param	string	$value
	 * @return	integer
	 */
	public static function length($value)
	{
		if (function_exists('mb_strlen')) {
			return mb_strlen($value, static::encoding());
		}
		return strlen($value);
	}
	
	/**
	 * 将字符串转换为小写
	 *
	 * @param	string	$value
	 * @return	string
	 */
	public static function lower($value)
	{
		if (function_exists('mb_strtolower')) {
			return mb_strtolower($value, static::encoding());
		}
		return strtolower($value);
	}
	
	/**
	 * 将字符串转换为大写
	 *
	 * @param	string	$value
	 * @return	string
	 */
	public static function upper($value)
	{
		if (function_exists('mb_strtoupper')) {
			return mb_strtoupper($value, static::encoding());
		}
		return strtoupper($value);
	}
	
	/**
	 * 转换字符串为标题, 即每个单词首字母大写
	 *
	 * @param	string	$value
	 * @return	string
	 */
	public static function title($value)
	{
		if (function_exists('mb_convert_case')) {
			mb_convert_case($value, MB_CASE_TITLE, static::encoding());
		}
		return ucwords(strtolower($value));
	}
	
	/**
	 * 限制字符个数
	 *
	 * @param	string	$value
	 * @param	integer	$limit
	 * @param	string	$end
	 * @return	string
	 */
	public static function limit($value, $limit = 100, $end = '...')
	{
		if (static::length($value) <= $limit) {
			return $value;
		}
		if (function_exists('mb_substr')) {
			return mb_substr($value, 0, $limit, static::encoding()).$end;
		}
		return substr($value, 0, $limit).$end;
	}
	
	/**
	 * 限制单词个数
	 *
	 * @param	string	$value
	 * @param	integer	$limit
	 * @param	string	$end
	 * @return	string
	 */
	public static function words($value, $limit = 100, $end = '..')
	{
		if (trim($value) === '') {
			return '';
		}
		preg_match('/^\s*+(?:\S++\s*+){1,'.$words.'}/u', $value, $matches);
		// 如果匹配了所有的字符串, 结束符为空字符串
		if (static::length($value) == static::length($matches[0])) {
			$end = '';
		}
		return rtrim($matches[0]).$end;
	}
	
	/**
	 * 获取指定词的单数词
	 *
	 * @param	string	$value
	 * @return	string
	 */
	public static function singular($value)
	{
		return static::pluralizer()->singular($value);
	}
	
	/**
	 * 获取指定词的复数词
	 *
	 * @param	string	$value
	 * @return	string
	 */
	public static function plural($value)
	{
		return static::pluralizer()->plural($value);
	}
	
	/**
	 * 根据指定的字符串创建友好的URL
	 *
	 * @param	string	$title
	 * @param	string	$separator
	 * @return	string
	 */
	public static function slug($title, $separator = '_')
	{
		$title = static::ascii($title);
		// 移除所有非$separator, 字母, 数组, 空格字符
		$title = preg_replace('![^'.preg_quote($separator).'\pL\pN\s]+!u', '', static::lower($title));
		$title = preg_replace('!['.preg_quote($separator).'\s]+!u', $separator, $title);
		return trim($title, $separator);
	}
	
	/**
	 * 转换字符串为7为的ASCII, 中文直接被清楚
	 *
	 * @param	string	$value
	 * @return	void
	 */
	public static function ascii($value)
	{
		$foreign = Config::get('strings.ascii');
		$value = preg_replace(array_keys($foreign), array_values($foreign), $value);
		return preg_replace('/[^\x09\x0A\x0D\x20-\x7E]/', '', $value);
	}
	
	/**
	 * 生成类标示符, 如果是空格会替换成下划线, 并且首字母大写
	 *
	 * @param	string	$value
	 * @return	string
	 */
	public static function classify($value)
	{
		$search = array('_', '-', '.');
		return str_replace(' ', '_', static::title(str_replace($search, ' ', $value)));
	}
	
	/**
	 * 根据反斜杠将字符串分割为一个数组
	 *
	 * @param	string	$value
	 * @return	value
	 */
	public static function segments($value)
	{
		return array_diff(explode('/', trim($value, '/')), array(''));
	}
	
	/**
	 * 检测指定的字符串是否匹配给定的模式
	 *
	 * @param	string	$pattern
	 * @param	string	$value
	 * @return	boolean
	 */
	public static function is($pattern, $value)
	{
		if ($pattern !== '/') {
			$pattern = str_replace('*', '(.*)', $pattern).'\z';
		} else {
			$pattern = '^/$';
		}
		return preg_match('#'.$pattern.'#', $value);
	}
	
	/**
	 * 生成一个随机字符串
	 *
	 * @param	integer	$length
	 * @param	string	$type
	 * @return	string
	 */
	public static function random($length, $type = 'alnum')
	{
		return substr(str_shuffle(str_repeat(static::pool($type), 5)), 0, $length);
	}
	
	/**
	 * 根据指定的类型获取响应的字符串池, 用来产生随机字符串
	 *
	 * @param	string	$type
	 * @return	string
	 * @throws	Exception
	 */
	protected static function pool($type)
	{
		switch ($type) {
			case 'alpha':
				return 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
			case 'alnum':
				return '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
			default:
				throw new \Exception("Invalid random string type [$type].");
		}
	}
	
	/**
	 * 获取复数形式实例
	 *
	 * @return	Pluralizer
	 */
	protected static function pluralizer()
	{
		if (static::$pluralizer !== null) {
			return static::$pluralizer;
		}
		$config = Config::get('strings');
		return static::$pluralizer = new Pluralizer($config);
	}
}